package com.lc.utils;

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

/**
 * @author liuc
 * @date 2021/5/9
 * @description
 **/
public class ClassLoadUtil {

    public static Set<Class<?>> extractPackageClass(String packageName) {
        Set<Class<?>> classSet = new HashSet<>();
        //获取类的加载器，主要为了解决实际路径的问题，包名没办法定位
        ClassLoader classLoader = getClassLoader();
        //通过类加载器加载资源
        File packageDir = new File(packageName);
        extractClassFile(classSet, packageDir, packageName);
        return classSet;
    }

    //提取类文件（需要进行递归，判断是不是文件夹还是文件）
    private static void extractClassFile(final Set<Class<?>> classSet, File fileSoucre, final String packageName) {
        //如果是文件的情况
        if (!fileSoucre.isDirectory()) {
            return;
        } else {
            //文件夹的情况，列出文件夹下的所有文件
            File[] files = fileSoucre.listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    if (file.isDirectory()) {
                        return true;
                    } else {
                        //获取文件的绝对路径
                        String absolutePath = file.getAbsolutePath();
                        if (absolutePath.endsWith(".class")) {
                            //class文件直接加载
                            add2ClassSet(absolutePath);
                            return true;
                        }

                    }
                    return false;
                }

                /**
                 * 添加class到classSet当中
                 *
                 * @param absolutePath
                 */
                private void add2ClassSet(String absolutePath) {
                    String class1Name = absolutePath.replace(packageName+"/","");
                    String class2Name = class1Name.replaceAll("/", ".");
                    class2Name = class2Name.substring(class2Name.indexOf(".")+1);
                    String className = class2Name.substring(0, class2Name.lastIndexOf('.'));
                    Class<?> aClass = loadClass(className);
                    classSet.add(aClass);
                }

                private Class<?> loadClass(String className) {
                    try {
                        return Class.forName(className);
                    } catch (Exception ex) {
                        System.out.println("load class error");
                        throw new RuntimeException();
                    }
                }

            });

            if (files != null) {
                //遍历每一个文件
                for (File f : files) {
                    extractClassFile(classSet, f, packageName);
                }
            }
        }
    }

    /**
     * 获取ClassLoader
     *
     * @return
     */
    public static ClassLoader getClassLoader() {
        //通过这个方式获取ClassLoader实例
        return Thread.currentThread().getContextClassLoader();
    }

    public static void main(String[] args) {
        String pkg = "/Users/liuxiaolu/IdeaProjects/lagou-work/minicat/webapps";
        Set<Class<?>> classes = ClassLoadUtil.extractPackageClass(pkg);
        System.out.println(classes.size());
    }

}
